package com.engine.salary.service.impl;

import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.biz.SalaryArchiveBiz;
import com.engine.salary.biz.SalaryArchiveItemBiz;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.constant.SalaryItemConstant;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryarchive.bo.SalaryArchiveExcelBO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveInitImportDTO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveListDTO;
import com.engine.salary.entity.salaryarchive.param.SalaryArchiveImportActionParam;
import com.engine.salary.entity.salaryarchive.param.SalaryArchiveImportHandleParam;
import com.engine.salary.entity.salaryarchive.param.SalaryArchiveQueryParam;
import com.engine.salary.entity.salaryarchive.po.SalaryArchiveItemPO;
import com.engine.salary.entity.salaryarchive.po.SalaryArchivePO;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.param.SalarySobRangeSaveParam;
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO;
import com.engine.salary.entity.taxagent.param.TaxAgentRangeSaveParam;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.auth.AuthFilterTypeEnum;
import com.engine.salary.enums.datacollection.UseEmployeeTypeEnum;
import com.engine.salary.enums.salaryarchive.SalaryArchiveImportTypeEnum;
import com.engine.salary.enums.salaryarchive.SalaryArchiveListTypeEnum;
import com.engine.salary.enums.salaryarchive.SalaryArchiveStatusEnum;
import com.engine.salary.service.*;
import com.engine.salary.service.auth.AuthService;
import com.engine.salary.service.auth.AuthServiceImpl;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
import com.engine.salary.sys.service.SalarySysConfService;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.SalaryLoggerUtil;
import com.engine.salary.util.excel.ExcelComment;
import com.engine.salary.util.excel.ExcelParseHelper;
import com.engine.salary.util.excel.ExcelSupport;
import com.engine.salary.util.excel.ExcelUtilPlus;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.file.ImageFileManager;
import weaver.general.Util;
import weaver.hrm.User;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import static com.engine.salary.util.excel.ExcelSupport.EXCEL_TYPE_XLSX;

/**
 * @Description: 薪资档案
 * @Author: wangxiangzhong
 * @Date: 2021-11-03 10:51
 */
public class SalaryArchiveExcelServiceImpl extends Service implements SalaryArchiveExcelService {

    private SalaryArchiveItemService salaryArchiveItemService(User user) {
        return ServiceUtil.getService(SalaryArchiveItemServiceImpl.class, user);
    }


    private SalaryArchiveService salaryArchiveService(User user) {
        return ServiceUtil.getService(SalaryArchiveServiceImpl.class, user);
    }


    private TaxAgentService getTaxAgentService(User user) {
        return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
    }

    private SalaryEmployeeService getSalaryEmployeeService(User user) {
        return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

    public TaxAgentManageRangeService getTaxAgentManageRangeService(User user) {
        return ServiceUtil.getService(TaxAgentManageRangeServiceImpl.class, user);
    }

    private SalarySobRangeService getSalarySobRangeService(User user) {
        return ServiceUtil.getService(SalarySobRangeServiceImpl.class, user);
    }

    public SalarySysConfService getSalarySysConfService(User user) {
        return ServiceUtil.getService(SalarySysConfServiceImpl.class, user);
    }

    public AuthService getAuthService(User user) {
        return ServiceUtil.getService(AuthServiceImpl.class, user);
    }

    private SalaryArchiveBiz salaryArchiveMapper = new SalaryArchiveBiz();
    private SalaryArchiveItemBiz salaryArchiveItemMapper = new SalaryArchiveItemBiz();

//    private SalaryArchiveSobService salaryArchiveSobService;
//
//    private SalaryEmployeeService salaryEmployeeService;
//
//    private HrmCommonHrmStatusService hrmCommonHrmStatusService;
//
//    private BaseEnvInfoService baseEnvInfoService;

//    @Override
//    public void exportList(Map<String, Object> map, SalaryArchiveQueryParam queryParam, Long employeeId, String tenantKey) {
//        // 待定薪列表
//        boolean isPendingList = queryParam.getListType().equals(SalaryArchiveListTypeEnum.PENDING);
//        // 定薪列表
//        boolean isFixedList = queryParam.getListType().equals(SalaryArchiveListTypeEnum.FIXED);
//        // 待停薪列表
//        boolean isSuspendList = queryParam.getListType().equals(SalaryArchiveListTypeEnum.SUSPEND);
//        // 停薪列表
//        boolean isStopList = queryParam.getListType().equals(SalaryArchiveListTypeEnum.STOP);
//        if (isPendingList) {
//            queryParam.setRunStatusList(Arrays.asList(SalaryArchiveStatusEnum.PENDING.getValue()));
//        } else if (isFixedList) {
//            queryParam.setRunStatusList(Arrays.asList(SalaryArchiveStatusEnum.FIXED.getValue(), SalaryArchiveStatusEnum.SUSPEND.getValue()));
//        } else if (isSuspendList) {
//            queryParam.setRunStatusList(Arrays.asList(SalaryArchiveStatusEnum.SUSPEND.getValue()));
//        } else if (isStopList) {
//            queryParam.setRunStatusList(Arrays.asList(SalaryArchiveStatusEnum.STOP_FROM_PENDING.getValue(), SalaryArchiveStatusEnum.STOP_FROM_SUSPEND.getValue()));
//        }
//        String nameI18n = SalaryI18nUtil.getI18nLabel(85368, "薪资档案") +
//                SalaryI18nUtil.getI18nLabel(queryParam.getListType().getLabelId(), queryParam.getListType().getDefaultLabel());
//        String payStartDateI18n = SalaryI18nUtil.getI18nLabel(109527, "起始发薪日期");
//        String payEndDateI18n = SalaryI18nUtil.getI18nLabel(109329, "最后发薪日期");
//        String effectiveTimeI18n = SalaryI18nUtil.getI18nLabel(85904, "生效日期");
//
//        List<ExcelSheetData> sheetList = new ArrayList<>();
//        ExcelSheetData excelSheetData = new ExcelSheetData();
//        // 1.工作簿名称
////        excelSheetData.setSheetName(nameI18n);
////        boolean enableHr = baseEnvInfoService.checkDisplayModule(HrmModuleConstancts.hr, tenantKey);
//        List<String> headerList = Lists.newArrayList();
//        headerList.add(SalaryI18nUtil.getI18nLabel(85429, "姓名"));
//        headerList.add(SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"));
//        headerList.add(SalaryI18nUtil.getI18nLabel(121908, "收入所得项目"));
//        headerList.add(SalaryI18nUtil.getI18nLabel(87889, "薪资账套"));
//        headerList.add(SalaryI18nUtil.getI18nLabel(86319, "入职日期"));
//        headerList.add(SalaryI18nUtil.getI18nLabel(86185, "部门"));
//        headerList.add(SalaryI18nUtil.getI18nLabel(86186, "手机号"));
//        headerList.add(SalaryI18nUtil.getI18nLabel(86317, "工号"));
////        if (enableHr) {
////            headerList.add(SalaryI18nUtil.getI18nLabel(106277, "身份证号码"));
////        }
//        headerList.add(SalaryI18nUtil.getI18nLabel(109332, "人事状态"));
//        headerList.add(payStartDateI18n);
//        headerList.add(payEndDateI18n);
//        if (isFixedList) {
//            headerList.add(effectiveTimeI18n);
//        }
//        // 获取所有可被引用的薪资项目
//        List<SalaryItemPO> salaryItems = salaryArchiveItemService.getCanAdjustSalaryItems(tenantKey);
//        for (SalaryItemPO salaryItem : salaryItems) {
//            headerList.add(salaryItem.getName());
//        }
//        // 2.表头
//        excelSheetData.setHeaders(Collections.singletonList(headerList.toArray(new String[]{})));
//        // 获取所有个税扣缴义务人
//        Collection<TaxAgentListDTO> taxAgentList = getTaxAgentService().findAll(tenantKey);
//        Collection<SalaryArchiveListDTO> salaryArchives = salaryArchiveMapper.list(queryParam, tenantKey);
//        boolean isSearchIdNo = enableHr && StringUtils.isNotEmpty(queryParam.getIdNo());
//        if (isSearchIdNo) {
//            Map<Long, String> idNoEmpMap = salaryEmployeeService
//                    .mapByEmployeeIds(salaryArchives.stream().map(SalaryArchiveListDTO::getEmployeeId).distinct().collect(Collectors.toList()), tenantKey);
//            salaryArchives = salaryArchives.stream().filter(f -> Optional.ofNullable(idNoEmpMap.get(f.getEmployeeId())).orElse("").contains(queryParam.getIdNo()))
//                    .collect(Collectors.toList());
//        }
//        // 开启分权并且不是薪酬模块总管理员
//        boolean isChief = getTaxAgentService().isChief(employeeId, tenantKey);
//        if (getTaxAgentService().isOpenDevolution(tenantKey) && !isChief) {
//            List<TaxAgentEmployeeDTO> taxAgentEmployees = getTaxAgentService().listTaxAgentAndEmployee(employeeId, tenantKey);
//            List<Long> taxAgentIdsAsAdmin = getTaxAgentService().listAllTaxAgentsAsAdmin(employeeId, tenantKey).stream().map(TaxAgentPO::getId).collect(Collectors.toList());
//            salaryArchives = salaryArchives.stream().filter(f ->
//                    // 作为管理员
//                    taxAgentIdsAsAdmin.contains(f.getTaxAgentId())
//                            // 作为分管理员
//                            || TaxAgentBO.checkTaxAgentAndEmployee(taxAgentEmployees, f.getTaxAgentId(), f.getEmployeeId())
//                            || employeeId.equals(f.getModifier())
//            ).collect(Collectors.toList());
//        }
//        Map<Long, String> idNoEmpMap =
//                enableHr ? salaryEmployeeService.mapByEmployeeIds(salaryArchives.stream().map(SalaryArchiveListDTO::getEmployeeId).distinct().collect(Collectors.toList()), tenantKey)
//                        : new HashMap<>();
//        List<Map<String, Object>> listMaps = salaryArchiveService
//                .buildSalaryArchiveData(salaryArchives, taxAgentList, salaryItems, idNoEmpMap, employeeId, tenantKey, Boolean.FALSE);
//        // 组装数据
//        List<List<Object>> rows = new ArrayList<>();
//        listMaps.forEach(e -> {
//            List<Object> row = new ArrayList<>();
//            row.add(Optional.ofNullable(e.get("username")).orElse("").toString());
//            row.add(e.get("taxAgentName").toString());
//            row.add(e.get("incomeCategory").toString());
//            row.add(e.get("salarySob").toString());
//            row.add(Optional.ofNullable(e.get("hiredate")).orElse("").toString());
//            row.add(Optional.ofNullable(e.get("departmentName")).orElse("").toString());
//            row.add(Optional.ofNullable(e.get("mobile")).orElse("").toString());
//            row.add(Optional.ofNullable(e.get("jobNum")).orElse("").toString());
//            if (enableHr) {
//                row.add(Optional.ofNullable(e.get("idNo")).orElse("").toString());
//            }
//            row.add(e.get("employeeStatus").toString());
//            row.add(e.get("payStartDate").toString());
//            row.add(e.get("payEndDate").toString());
//            if (isFixedList) {
//                row.add(Optional.ofNullable(e.get("effectiveTime")).orElse("").toString());
//            }
//            // 薪资项目数据
//            for (SalaryItemPO salaryItem : salaryItems) {
//                row.add(e.containsKey(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) ? (e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) == null ? ""
//                        : e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX).toString()) : "");
//            }
//            rows.add(row);
//        });
//        // 3.表数据
//        excelSheetData.setRows(rows);
//
//        sheetList.add(excelSheetData);
//
//        salaryBatchService.simpleExportExcel(ExportExcelInfo.builder()
//                .bizId(map.get("biz").toString())
//                .flag(true)
//                .userId(employeeId)
//                .eteamsId(map.get("eteamsId").toString())
//                .tenantKey(tenantKey)
//                .operator(map.get("username").toString())
//                .module(map.get("module").toString())
//                .fileName(nameI18n + SalaryDateUtil.getFormatLocalDateTime(LocalDateTime.now()))
//                .handlerName("exportSalaryArchive")
//                .dataType(nameI18n)
//                .function("exportSalaryArchive").build(), sheetList);
//    }


    @Override
    public XSSFWorkbook downloadTemplate(SalaryArchiveQueryParam queryParam) {
        // 待定薪列表
        boolean isPendingList = queryParam.getListType().equals(SalaryArchiveListTypeEnum.PENDING);
        // 定薪列表
        boolean isFixedList = queryParam.getListType().equals(SalaryArchiveListTypeEnum.FIXED);
        // 待停薪列表
        boolean isSuspendList = queryParam.getListType().equals(SalaryArchiveListTypeEnum.SUSPEND);
        if (isPendingList) {
            queryParam.setRunStatusList(Arrays.asList(SalaryArchiveStatusEnum.PENDING.getValue()));
        } else if (isFixedList) {
            queryParam.setRunStatusList(Arrays.asList(SalaryArchiveStatusEnum.FIXED.getValue(), SalaryArchiveStatusEnum.SUSPEND.getValue()));
        } else if (isSuspendList) {
            queryParam.setRunStatusList(Arrays.asList(SalaryArchiveStatusEnum.SUSPEND.getValue()));
        }

        boolean isInit = queryParam.getImportType().equals(SalaryArchiveImportTypeEnum.INIT.getValue());
        boolean isSalaryItemAdjust = queryParam.getImportType().equals(SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getValue());
        // 名称
        String nameI18n = SalaryI18nUtil.getI18nLabel(101601, "薪资档案导入模板")
                + SalaryI18nUtil.getI18nLabel(queryParam.getListType().getLabelId(), queryParam.getListType().getDefaultLabel());
        if (isFixedList) {
            // 初始化
            if (isInit) {
                nameI18n +=
                        "-" + SalaryI18nUtil.getI18nLabel(SalaryArchiveImportTypeEnum.INIT.getLabelId(), SalaryArchiveImportTypeEnum.INIT.getDefaultLabel());
                // 调薪
            } else if (isSalaryItemAdjust) {
                nameI18n += "-" + SalaryI18nUtil
                        .getI18nLabel(SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getLabelId(), SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getDefaultLabel());
            }
        }
        String finalNameI18n = nameI18n;

        // 获取所有可被引用的薪资项目
        List<SalaryItemPO> salaryItems = salaryArchiveItemService(user).getCanAdjustSalaryItems();
//        boolean enableHr = baseEnvInfoService.checkDisplayModule(HrmModuleConstancts.hr, tenantKey);
        List<Object> header = Lists.newArrayList();
        header.add(SalaryI18nUtil.getI18nLabel(85429, "姓名"));
        header.add(SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"));
//        header.add(SalaryI18nUtil.getI18nLabel(121908, "收入所得项目"));
//        header.add(SalaryI18nUtil.getI18nLabel(87889, "薪资账套"));
//        header.add(SalaryI18nUtil.getI18nLabel(86319, "入职日期"));
        header.add(SalaryI18nUtil.getI18nLabel(86185, "部门"));
        header.add(SalaryI18nUtil.getI18nLabel(1933, "工号"));
        header.add(SalaryI18nUtil.getI18nLabel(86186, "手机号"));
        header.add(SalaryI18nUtil.getI18nLabel(86186, "证件号码"));
        header.add(SalaryI18nUtil.getI18nLabel(15890, "员工状态"));
//        if (enableHr) {
//            header.add(SalaryI18nUtil.getI18nLabel(106277, "身份证号码"));
//        }
//        header.add(SalaryI18nUtil.getI18nLabel(109332, "人事状态"));
        String payStartDateI18n = SalaryI18nUtil.getI18nLabel(109527, "起始发薪日期");
        String payEndDateI18n = SalaryI18nUtil.getI18nLabel(109329, "最后发薪日期");
        String adjustReasonI18n = SalaryI18nUtil.getI18nLabel(85431, "调整原因");
        String effectiveTimeI18n = SalaryI18nUtil.getI18nLabel(85904, "生效日期");
        if (isPendingList) {
            header.add(payStartDateI18n);
            header.add(payEndDateI18n);
        } else if (isFixedList) {
            if (isInit) {
                header.add(payStartDateI18n);
                header.add(payEndDateI18n);
                header.add(effectiveTimeI18n);
            } else if (isSalaryItemAdjust) {
                header.add(adjustReasonI18n);
                header.add(effectiveTimeI18n);
            }
        } else if (isSuspendList) {
            header.add(payStartDateI18n);
            header.add(payEndDateI18n);
        }
        for (SalaryItemPO salaryItem : salaryItems) {
            header.add(salaryItem.getName());
        }
        // 2.表头
        List<List<Object>> rows = new ArrayList<>();
        rows.add(header);
        // 获取所有个税扣缴义务人
        Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAll();
        List<SalaryArchiveListDTO> salaryArchives = salaryArchiveService(user).getSalaryArchiveList(queryParam);
        salaryArchives = getAuthService(user).auth(salaryArchives, AuthFilterTypeEnum.ADMIN_DATA, SalaryArchiveListDTO.class);

        if (queryParam.getHasData()) {
            List<Map<String, Object>> listMaps = salaryArchiveService(user)
                    .buildSalaryArchiveData(salaryArchives, taxAgentList, salaryItems, Boolean.FALSE);
            // 组装数据
            listMaps.forEach(e -> {
                List<Object> row = new ArrayList<>();
                row.add(e.get("username").toString());
                row.add(e.get("taxAgentName").toString());
//            row.add(e.get("incomeCategory").toString());
//            row.add(e.get("salarySob").toString());
//            row.add(e.get("hiredate"));
                row.add(Optional.ofNullable(e.get("departmentName")).orElse("").toString());
                row.add(Optional.ofNullable(e.get("workcode")).orElse("").toString());
                row.add(e.get("mobile") == null ? "" : e.get("mobile").toString());
                row.add(Util.null2String(e.get("idNo")));
                row.add(Util.null2String(e.get("employeeStatus")));
//            if (enableHr) {
//                row.add(Optional.ofNullable(e.get("idNo")).orElse("").toString());
//            }
//            row.add(e.get("employeeStatus").toString());
                if (isPendingList) {
                    row.add(e.get("payStartDate").toString());
                    row.add(e.get("payEndDate").toString());
                } else if (isFixedList) {
                    if (isInit) {
                        row.add(e.get("payStartDate").toString());
                        row.add(e.get("payEndDate").toString());
                        row.add(Optional.ofNullable(e.get("effectiveTime")).orElse("").toString());
                    } else if (isSalaryItemAdjust) {
                        row.add(Optional.ofNullable(e.get("adjustReason")).orElse("").toString());
                        row.add(Optional.ofNullable(e.get("effectiveTime")).orElse("").toString());
                    }
                } else if (isSuspendList) {
                    row.add(e.get("payStartDate").toString());
                    row.add(e.get("payEndDate").toString());
                }
                // 薪资项目数据
                for (SalaryItemPO salaryItem : salaryItems) {
                    row.add(e.containsKey(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) ? (e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) == null ? ""
                            : e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX).toString()) : "");
                }
                rows.add(row);
            });
        }


        // 4.注释
        List<ExcelComment> excelComments = Lists.newArrayList();
        String requireI18n = SalaryI18nUtil.getI18nLabel(100344, "必填");
        excelComments.add(new ExcelComment(0, 0, 1, 2, requireI18n));
        excelComments.add(new ExcelComment(1, 0, 2, 2, requireI18n));
        //收入所得项目
//        List<String> incomeCategoryOptions = Arrays.stream(IncomeCategoryEnum.values()).map(e ->
//                SalaryI18nUtil.getI18nLabel(e.getLabelId(), e.getDefaultLabel())
//        ).collect(Collectors.toList());
//        SalaryArchiveExcelBO
//                .createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(121922, "必填,可填写如:") + Joiner.on(",").join(incomeCategoryOptions), 0, 0, 2, 2);
//        SalaryArchiveExcelBO.createExcelComment(excelComments, requireI18n + '，' + SalaryI18nUtil.getI18nLabel(127641, "多个账套之间用,分隔"), 0, 0, 3, 3);
//        int i = enableHr ? 10 : 9;
        if (isPendingList) {
            excelComments.add(new ExcelComment(7, 0, 9, 2, SalaryI18nUtil.getI18nLabel(100458, "格式样例为'2022-01-01'、'2022/1/1'")));
//                excelComments.add(new ExcelComment(5, 0, 8, 2, SalaryI18nUtil.getI18nLabel(100458, "格式样例为'2022-01-01'、'2022/1/1'")));
        } else if (isFixedList) {
            if (isInit) {
                excelComments.add(new ExcelComment(7, 0, 9, 2, SalaryI18nUtil.getI18nLabel(100458, "必填，格式样例为'2022-01-01'、'2022/1/1'")));
                excelComments.add(new ExcelComment(8, 0, 10, 2, SalaryI18nUtil.getI18nLabel(100458, "格式样例为'2022-01-01'、'2022/1/1'")));
                excelComments.add(new ExcelComment(9, 0, 11, 2, SalaryI18nUtil.getI18nLabel(100458, "必填，格式样例为'2022-01-01'、'2022/1/1'")));
            } else if (isSalaryItemAdjust) {
                excelComments.add(new ExcelComment(7, 0, 9, 2, SalaryI18nUtil.getI18nLabel(100458, "必填,可填写如:入职,转正,调薪,晋升,降职,调岗,调岗调薪,离职,其他,初始化")));
                excelComments.add(new ExcelComment(8, 0, 10, 2, SalaryI18nUtil.getI18nLabel(100458, "必填，格式样例为'2022-01-01'、'2022/1/1'")));
            }
        } else if (isSuspendList) {
//            SalaryArchiveExcelBO.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(109736, "格式样例为'2022-01-01'、'2022/1/1'"), 0, 0, i + 1, i + 1);
        }

//        return ExcelUtil.genWorkbookV2(rows, finalNameI18n, excelComments);
        return ExcelUtilPlus.genWorkbookV2(rows, finalNameI18n, excelComments);
    }

//    /**
//     * 导入薪资档案
//     */
//    @BatchImportHandler("importSalaryArchive")
//    @Transactional(rollbackFor = Exception.class)
//    public void importSalaryArchive() {
//        BatchDocumentMessage message = BatchImportContext.getBatchDocumentMessage();
//        log.info("【薪资档案】接收到上传的数据：{}", String.format("batchTaskId=%s, fileName=%s", message.getBatchTaskId(), message.getBatchFile().getName()));
//        // 租户key
//        String tenantKey = message.getTenantKey().toLowerCase();
//        try {
//            // 加密用
//            DSTenantKeyThreadVar.tenantKey.set(tenantKey);
//            // 接收到解析的数据
//            batchImportEbatch(message);
//        } catch (Exception e) {
//            log.error("【薪资档案】导入失败：{}", String.format("batchTaskId=%s,错误信息=%s", message.getBatchTaskId(), e.getMessage()));
//        } finally {
//            // 加密用
//            DSTenantKeyThreadVar.tenantKey.remove();
//        }
//    }


    public Map<String, Object> batchImportEbatch(SalaryArchiveImportHandleParam param) {
        // 初始化国际化标签
        SalaryArchiveExcelBO.initI18n();

        String imageId = param.getImageId();
        // 构建导入需要的数据
        SalaryArchiveImportHandleParam importHandleParam = buildImportHandleParam(param);

        InputStream fileInputStream = null;
        try {
            fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(imageId));
            Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX);


            int total = 0;
            //excel数据
            List<Map<String, Object>> data = ExcelParseHelper.parse2Map(sheet, 1);
            if (data != null) {
                total += data.size();
            }

            int index = 0;
            int successCount = 0;
            int errorCount = 0;
            // 错误excel内容
//            List<ExcelSheet> errorExcelSheets = new ArrayList<>();
            // 用于（初始化导入）的相同employeeId时的处理
            List<SalaryArchiveInitImportDTO> initImportData = Lists.newArrayList();
            // 用于（调薪和调整个税扣缴义务人）的相同employeeId时取第一条记录,如果是初始化导入则有重复
            List<String> allTodoSalaryArchives = Lists.newArrayList();
//            if (excelSheet.getHeader().size() == 0) {
//                continue;
//            }
            List<String> headers = ExcelSupport.getSheetHeader(sheet, 0);

            // 错误提示
            List<Map<String, String>> excelComments = new ArrayList<>();
            HashMap message = new HashMap();
            boolean isValidHeader = checkHeaders(importHandleParam, message, headers);
            if (!isValidHeader) {
                excelComments.add(message);
                Map<String, Object> apidatas = new HashMap<>();
                apidatas.put("successCount", successCount);
                apidatas.put("errorCount", errorCount);
                apidatas.put("errorNotice", excelComments);
                return apidatas;
            }
            int effectiveTimeIndex = 0;
            for (int j = 0; j < headers.size(); j++) {
                String header = headers.get(j);
                String key = header;
                if (key.equals(SalaryI18nUtil.getI18nLabel(85904, "生效日期"))) {
                    effectiveTimeIndex = j;
                }
            }
            // 错误sheet数据
            List<Map<String, Object>> errorData = new ArrayList<>();
            // 获取匹配规则
            SalarySysConfPO salarySysConfPO = getSalarySysConfService(user).getOneByCode("matchEmployeeMode");
            String confValue = (salarySysConfPO != null && salarySysConfPO.getConfValue() != null && !"".equals(salarySysConfPO.getConfValue())) ? salarySysConfPO.getConfValue() : "0";

            Map<String, Object> map;
            for (int i = 0; i < data.size(); i++) {
                index += 1;
                map = data.get(i);
                map.put("index", i + 2);
                // 3.校验行内容
                boolean isError = SalaryArchiveExcelBO.singleRowCheck(allTodoSalaryArchives, map, headers, effectiveTimeIndex, excelComments, errorCount, importHandleParam, user);
                if (isError) {
                    errorCount += 1;
                    // 添加错误数据
                    errorData.add(map);
                } else {
                    successCount += 1;
                }
                // 初始化导入对重复记录校验
                if (importHandleParam.isInit()) {
                    Map<String, Object> validMap = SalaryArchiveExcelBO
                            .validInitImportData(isError, i + 1, map, excelComments, errorCount, successCount, errorData, initImportData, importHandleParam);
                    errorCount = Integer.parseInt(validMap.getOrDefault("errorCount", errorCount).toString());
                    successCount = Integer.parseInt(validMap.getOrDefault("successCount", successCount).toString());
                }
                // 导入进度
//                    if (index % 100 == 0 || index >= total) {
//                        salaryBatchService.sendImportRate(message.getBizId(), total, index);
//                    }
            }

            // 如果sheet包含错误数据
            if (CollectionUtils.isNotEmpty(errorData)) {
//                    salaryBatchService.createErrorExcelSheet(headers, errorData, excelSheet.getName(), excelComments, errorExcelSheets);
            }

            // 4.数据入库处理
            if (!param.isOnlyCheck()) {
                handleImportData(importHandleParam);
            }

            Map<String, Object> apidatas = new HashMap<>();

            apidatas.put("successCount", successCount);
            apidatas.put("errorCount", errorCount);
            apidatas.put("errorNotice", excelComments);
            return apidatas;

            // 发送导入回调信息
//            salaryBatchService.sendImportCallBackInfo(message, successCount, errorCount, errorExcelSheets);

        } finally {
            IOUtils.closeQuietly(fileInputStream);
        }
    }


    public Map<String, Object> processInit(SalaryArchiveImportActionParam param) {
        // 初始化国际化标签
        SalaryArchiveExcelBO.initI18n();


        // 构建导入需要的数据
        SalaryArchiveImportHandleParam importHandleParam = buildImportHandleParam(SalaryArchiveImportHandleParam.builder().isProcess(true).listType(param.getListType()).importType(param.getImportType()).description(param.getDescription()).build());
        importHandleParam.setKeepStatus(param.getKeepStatus());

        int total = 0;
        //excel数据
        // 需要导入的数据
        List<Map<String, Object>> data = param.getImportDatas();
        if (data != null) {
            total += data.size();
        }

        int index = 0;
        int successCount = 0;
        int errorCount = 0;
        // 错误excel内容
//            List<ExcelSheet> errorExcelSheets = new ArrayList<>();
        // 用于（初始化导入）的相同employeeId时的处理
        List<SalaryArchiveInitImportDTO> initImportData = Lists.newArrayList();
        // 用于（调薪和调整个税扣缴义务人）的相同employeeId时取第一条记录,如果是初始化导入则有重复
        List<String> allTodoSalaryArchives = Lists.newArrayList();


        // 错误提示
        List<Map<String, String>> excelComments = new ArrayList<>();
        HashMap message = new HashMap();

        // 错误sheet数据
        List<Map<String, Object>> errorData = new ArrayList<>();

        for (int i = 0; i < data.size(); i++) {
            Map<String, Object> map = data.get(i);
            List<String> headers = Lists.newArrayList();
            map.keySet().forEach(headers::add);
            int effectiveTimeIndex = 0;
            for (int j = 0; j < headers.size(); j++) {
                String header = headers.get(j);
                String key = header;
                if (key.equals(SalaryI18nUtil.getI18nLabel(85904, "生效日期"))) {
                    effectiveTimeIndex = j;
                }
            }
            boolean isValidHeader = checkHeaders(importHandleParam, message, headers);
            if (!isValidHeader) {
                excelComments.add(message);
                Map<String, Object> apidatas = new HashMap<>();
                apidatas.put("successCount", successCount);
                apidatas.put("errorCount", errorCount);
                apidatas.put("errorNotice", excelComments);
                return apidatas;
            }

            index += 1;
            map = data.get(i);
            map.put("index", i + 2);
            // 3.校验行内容
            boolean isError = SalaryArchiveExcelBO.singleRowCheck(allTodoSalaryArchives, map, headers, effectiveTimeIndex, excelComments, errorCount, importHandleParam, user);
            if (isError) {
                errorCount += 1;
                // 添加错误数据
                errorData.add(map);
            } else {
                successCount += 1;
            }
            // 初始化导入对重复记录校验
            if (importHandleParam.isInit()) {
                Map<String, Object> validMap = SalaryArchiveExcelBO
                        .validInitImportData(isError, i, map, excelComments, errorCount, successCount, errorData, initImportData, importHandleParam);
                errorCount = Integer.parseInt(validMap.getOrDefault("errorCount", errorCount).toString());
                successCount = Integer.parseInt(validMap.getOrDefault("successCount", successCount).toString());
            }
            // 导入进度
//                    if (index % 100 == 0 || index >= total) {
//                        salaryBatchService.sendImportRate(message.getBizId(), total, index);
//                    }
        }

        // 如果sheet包含错误数据
        if (CollectionUtils.isNotEmpty(errorData)) {
//                    salaryBatchService.createErrorExcelSheet(headers, errorData, excelSheet.getName(), excelComments, errorExcelSheets);
        }

        // 4.数据入库处理
        if (param.isAddData()) {
            handleImportData(importHandleParam);
        }

        Map<String, Object> apidatas = new HashMap<>();

        apidatas.put("successCount", successCount);
        apidatas.put("errorCount", errorCount);
        apidatas.put("errorNotice", excelComments);
        return apidatas;

        // 发送导入回调信息
//            salaryBatchService.sendImportCallBackInfo(message, successCount, errorCount, errorExcelSheets);

    }


    /**
     * 构建导入处理参数
     *
     * @param param
     * @return
     */
    private SalaryArchiveImportHandleParam buildImportHandleParam(SalaryArchiveImportHandleParam param) {

        // 列表类型
        String listType = param.getListType();
        // 导入类型
        String importType = param.getImportType();

        // 获取所有可被引用的薪资项目
        List<SalaryItemPO> salaryItems = salaryArchiveItemService(user).getCanAdjustSalaryItems();
        Collection<Long> salaryItemIds = salaryItems.stream().map(SalaryItemPO::getId).collect(Collectors.toList());
        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList;
        if (param.isProcess()) {
            // 获取所有个税扣缴义务人
            taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree();
        } else {
            taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree((long) user.getUID());
        }

        // 待定薪列表
        boolean isPendingList = listType.equals(SalaryArchiveListTypeEnum.PENDING.getValue());
        // 定薪列表
        boolean isFixedList = listType.equals(SalaryArchiveListTypeEnum.FIXED.getValue());
        // 待停薪列表
        boolean isSuspendList = listType.equals(SalaryArchiveListTypeEnum.SUSPEND.getValue());

        boolean isInit = isFixedList && importType.equals(SalaryArchiveImportTypeEnum.INIT.getValue());
        boolean isSalaryItemAdjust = isFixedList && importType.equals(SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getValue());
        // 初始化导入是先删除后增的，起始可以只加载非加密的列
        boolean isNoNeedSalaryItem = isPendingList || isInit;

        List<String> runStatusList = Lists.newArrayList();// 初始化导入是全量
        if (isPendingList) {
            runStatusList = Arrays.asList(SalaryArchiveStatusEnum.PENDING.getValue());
        } else if (isSalaryItemAdjust) {
            runStatusList = Arrays.asList(SalaryArchiveStatusEnum.FIXED.getValue(), SalaryArchiveStatusEnum.SUSPEND.getValue());
        } else if (isSuspendList) {
            runStatusList = Arrays.asList(SalaryArchiveStatusEnum.FIXED.getValue(), SalaryArchiveStatusEnum.SUSPEND.getValue());
        }
        List<SalaryArchivePO> salaryArchiveList = salaryArchiveService(user).listSome(SalaryArchivePO.builder().runStatusList(runStatusList).build());
        List<Long> salaryArchiveIds = salaryArchiveList.stream().map(SalaryArchivePO::getId).collect(Collectors.toList());
        Map<String, SalaryArchivePO> salaryArchivesMap = SalaryEntityUtil.convert2Map(salaryArchiveList, k -> k.getEmployeeId() + "-" + k.getTaxAgentId());

        UseEmployeeTypeEnum empType = UseEmployeeTypeEnum.ORG;
        //外部人员导入
        if (param.isExtEmp()) {
            empType = UseEmployeeTypeEnum.EXT;
        }
        return SalaryArchiveImportHandleParam.builder()
                .isProcess(param.isProcess())
                .description(param.getDescription())
                .listType(listType)
                .importType(importType)
                .currentEmployeeId((long) user.getUID())
                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                //人员定位方式
                .empValidType(getSalaryEmployeeService(user).empValidType())
                // 待定薪列表
                .isPendingList(isPendingList)
                // 定薪列表
                .isFixedList(isFixedList)
                // 待停薪列表
                .isSuspendList(isSuspendList)
                //外部人员
                .isExtEmp(param.isExtEmp())
                // 初始化导入
                .isInit(isInit)
                // 调薪导入
                .isSalaryItemAdjust(isSalaryItemAdjust)
                // 获取租户下所有的人员
                .employees(getSalaryEmployeeService(user).listAll(empType))
//                .hrmStatusList(hrmStatusList)
                // 获取所有个税扣缴义务人
                .taxAgentList(taxAgentList)
                .salaryItems(salaryItems)
                // 查询已有的薪资档案基本数据
                .salaryArchivesMap(salaryArchivesMap)
                .salaryItemIds(salaryItemIds)
                // 查询已生效的薪资项目数据
                .effectiveItemListMap(
                        isSuspendList ? Collections.emptyMap() : salaryArchiveItemService(user).getEffectiveItemListMap(salaryArchiveIds, isNoNeedSalaryItem, salaryItemIds))
                // 查询未生效的薪资项目数据
                .ineffectiveItemListMap(
                        isSuspendList ? Collections.emptyMap() : salaryArchiveItemService(user).getIneffectiveItemListMap(salaryArchiveIds, isNoNeedSalaryItem, salaryItemIds))
                // 当前时间
                .nowTime(new Date())
                // 当天
                .today(new Date())
                // 待保存薪资档案
                .salaryArchiveSaves(Lists.newArrayList())
                // 待保存薪资档案-薪资项目
                .salaryArchiveItemSaves(Lists.newArrayList())
                // 待修改薪资档案-薪资项目
                .salaryArchiveUpdates(Lists.newArrayList())
                // 待删除薪资档案-薪资项目
                .salaryArchiveItemDelSalaryItemIds(Lists.newArrayList())
                //人员范围
                .taxAgentRanges(Lists.newArrayList())
                // 薪资账套
//                .salarySobList(salaryArchiveService.getSalarySobList(employeeId, tenantKey))
                // 待保存薪资档案-薪资账套
//                .salaryArchiveSobSaves(Lists.newArrayList())
                .build();
    }

    /**
     * 检查参数
     *
     * @param message
     * @param params
     * @return
     */
    private boolean checkParams(Map message, Map<String, Object> params) {
        boolean isValid = true;

        String errorMsg = SalaryArchiveExcelBO.handleCheckParams(message, params);
        // 有错误信息发送
        if (StringUtils.isNotEmpty(errorMsg)) {
            // 发送导入回调信息
//            salaryBatchService.sendImportCallBackInfo(message, errorMsg);
            isValid = false;
        }
        return isValid;
    }

    /**
     * 检查列头
     *
     * @param importHandleParam
     * @param message
     * @param headers
     * @return
     */
    private boolean checkHeaders(SalaryArchiveImportHandleParam importHandleParam, Map message, List<String> headers) {
        boolean isValid = true;

        String errorMsg = SalaryArchiveExcelBO.handleCheckHeaders(importHandleParam, message, headers);
        // 有错误信息发送
        if (StringUtils.isNotEmpty(errorMsg)) {
            message.put("message", errorMsg);
            // 发送导入回调信息
//            salaryBatchService.sendImportCallBackInfo(message, errorMsg);
            isValid = false;
        }
        return isValid;
    }

    /**
     * 数据落库处理
     *
     * @param importHandleParam
     */
    private void handleImportData(SalaryArchiveImportHandleParam importHandleParam) {
        List<SalaryArchivePO> salaryArchiveSaves = importHandleParam.getSalaryArchiveSaves();
        List<SalaryArchivePO> salaryArchiveUpdates = importHandleParam.getSalaryArchiveUpdates();
        List<SalaryArchiveItemPO> salaryArchiveItemSaves = importHandleParam.getSalaryArchiveItemSaves();
        List<Long> salaryArchiveItemDelSalaryItemIds = importHandleParam.getSalaryArchiveItemDelSalaryItemIds();
        List<TaxAgentRangeSaveParam> taxAgentRanges = importHandleParam.getTaxAgentRanges();
        List<SalarySobRangeSaveParam> salaryArchiveSobSaves = importHandleParam.getSalaryArchiveSobSaves();

        Map<Long, String> empMap = SalaryEntityUtil.convert2Map(importHandleParam.getEmployees(), DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getUsername);
        Map<Long, String> taxAgentMap = SalaryEntityUtil.convert2Map(importHandleParam.getTaxAgentList(), TaxAgentManageRangeEmployeeDTO::getTaxAgentId, TaxAgentManageRangeEmployeeDTO::getTaxAgentName);
        // 新增薪资档案
        if (CollectionUtils.isNotEmpty(salaryArchiveSaves)) {
            // 去除已经存在的，避免重复
            if (CollectionUtils.isNotEmpty(salaryArchiveUpdates)) {
                List<Long> salaryArchiveUpdateIds = salaryArchiveUpdates.stream().map(SalaryArchivePO::getId).distinct().collect(Collectors.toList());
                salaryArchiveSaves = salaryArchiveSaves.stream().filter(save -> !salaryArchiveUpdateIds.contains(save.getId())).collect(Collectors.toList());
            }
            // 薪资档案
            salaryArchiveMapper.batchInsert(salaryArchiveSaves);
        }
        // 修改薪资档案
        if (CollectionUtils.isNotEmpty(salaryArchiveUpdates)) {
            // 查询更新前档案信息
            List<SalaryArchivePO> oldArchive = salaryArchiveService(user).listSome(SalaryArchivePO.builder().ids(salaryArchiveUpdates.stream().map(SalaryArchivePO::getId).collect(Collectors.toList())).build());
            Map<Long, SalaryArchivePO> oldArchiveMap = SalaryEntityUtil.convert2Map(oldArchive, SalaryArchivePO::getId);
            // 薪资档案
            salaryArchiveMapper.batchUpdate(salaryArchiveUpdates);
            // 记录日志
            salaryArchiveUpdates.stream().forEach(a -> {
                SalaryArchivePO oldPO = oldArchiveMap.getOrDefault(a.getId(), SalaryArchivePO.builder().build());
                String name = taxAgentMap.getOrDefault(a.getTaxAgentId(), StringUtils.EMPTY) + "-" + empMap.getOrDefault(a.getEmployeeId(), StringUtils.EMPTY);
                SalaryLoggerUtil.recordUpdateSingleLog(SalaryElogConfig.salaryArchiveLoggerTemplate,
                        a.getId(),
                        name,
                        SalaryI18nUtil.getI18nLabel(0, "薪资档案导入更新"),
                        SalaryI18nUtil.getI18nLabel(0, "薪资档案导入更新") + name,
                        oldPO,
                        a,
                        user);
            });
        }
        //  薪资档案-薪资项目
        if (CollectionUtils.isNotEmpty(salaryArchiveItemDelSalaryItemIds)) {
            salaryArchiveItemMapper.deleteBatchIds(salaryArchiveItemDelSalaryItemIds);
        }
        // 薪资档案-薪资项目
        if (CollectionUtils.isNotEmpty(salaryArchiveItemSaves)) {
            salaryArchiveItemMapper.batchInsert(salaryArchiveItemSaves, user);
        }

        // 薪资档案-薪资账套
//        salaryArchiveSaves.addAll(salaryArchiveUpdates);
//        List<Long> salaryArchiveIds = salaryArchiveSaves.stream().map(SalaryArchivePO::getId).distinct().collect(Collectors.toList());
//        if (CollectionUtils.isNotEmpty(salaryArchiveIds) && CollectionUtils.isNotEmpty(salaryArchiveSaves)) {
//            this.salaryArchiveSobService.saveBatchBySalaryArchiveIdsAndSaves(salaryArchiveIds, salaryArchiveSobSaves, message.getTenantKey());
//        }


        //新增人员范围（会自动生成人员档案）
        if (CollectionUtils.isNotEmpty(taxAgentRanges)) {
            taxAgentRanges.forEach(getTaxAgentManageRangeService(user)::save);
        }

        if (CollectionUtils.isNotEmpty(salaryArchiveSobSaves)) {
            salaryArchiveSobSaves.forEach(getSalarySobRangeService(user)::save);
        }
    }
}
